package com.stek.utils;

import java.io.File;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.provider.MediaStore;
import android.support.v4.content.IntentCompat;
import android.support.v7.appcompat.R;

public class AppUtils {
	public static final int FILTER_ALL_APPS = 0;
	public static final int FILTER_APPS_RUNNING = FILTER_ALL_APPS + 1;
	public static final int FILTER_SYSTEMS_APPS = FILTER_ALL_APPS + 2;
	public static final int FILTER_APPS_SDCARD = FILTER_ALL_APPS + 3;
	public static final int FILTER_USER_APPS = FILTER_ALL_APPS + 4;

	// ==========================================================================
	public static ArrayList<ApplicationInfo> getAllKnownApplication(
			Context context) {
		PackageManager pm = context.getPackageManager();
		ArrayList<ApplicationInfo> apps = (ArrayList<ApplicationInfo>) pm
				.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
		ArrayList<ApplicationInfo> launchableApps = new ArrayList<ApplicationInfo>();
		if (apps == null) {
			apps = new ArrayList<ApplicationInfo>();
		}

		String ownPgk = context.getPackageName();
		for (ApplicationInfo app : apps) {
			Intent intent = pm.getLaunchIntentForPackage(app.packageName);
			if (intent != null && !ownPgk.equals(app.packageName)) {
				launchableApps.add(app);
			}
		}
		return launchableApps;
	}

	// ==========================================================================
	public static List<ApplicationInfo> getInstalledApplication(
			Context context, int filterOption) {
		PackageManager pm = context.getPackageManager();
		List<ApplicationInfo> installedAppList = pm
				.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES
						| PackageManager.GET_DISABLED_COMPONENTS);
		List<ApplicationInfo> appList = new ArrayList<ApplicationInfo>();
		String ownPgk = context.getPackageName();
		if (filterOption == FILTER_APPS_SDCARD) {
			for (ApplicationInfo appInfo : installedAppList) {
				if ((appInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0
						&& pm.getLaunchIntentForPackage(appInfo.packageName) != null
						&& !ownPgk.equals(appInfo.packageName)) {
					appList.add(appInfo);
				}
			}
			return appList;
		} else if (filterOption == FILTER_SYSTEMS_APPS) {
			for (ApplicationInfo appInfo : installedAppList) {
				if (((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 || (appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)
						&& pm.getLaunchIntentForPackage(appInfo.packageName) != null
						&& !ownPgk.equals(appInfo.packageName)) {
					appList.add(appInfo);
				}
			}
			return appList;
		} else if (filterOption == FILTER_USER_APPS) {
			for (ApplicationInfo appInfo : installedAppList) {
				if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
						&& pm.getLaunchIntentForPackage(appInfo.packageName) != null
						&& !ownPgk.equals(appInfo.packageName)) {
					appList.add(appInfo);
				}
			}
			return appList;
		} else if (filterOption == FILTER_APPS_RUNNING) {
			List<ActivityManager.RunningAppProcessInfo> procList = getRunningAppProcessesList(context);
			if ((procList == null) || (procList.size() == 0)) {
				return appList;
			}
			// Retrieve running processes from ActivityManager
			for (ActivityManager.RunningAppProcessInfo appProcInfo : procList) {
				if ((appProcInfo != null) && (appProcInfo.pkgList != null)
						&& (appProcInfo.pkgList.length != 0)) {
					int size = appProcInfo.pkgList.length;
					for (int i = 0; i < size; i++) {
						ApplicationInfo appInfo;
						try {
							appInfo = pm.getApplicationInfo(
									appProcInfo.pkgList[i],
									PackageManager.GET_UNINSTALLED_PACKAGES);
						} catch (NameNotFoundException e) {
							continue;
						}

						if (appInfo != null) {
							appList.add(appInfo);

						}
					}
				}
			}
			return appList;
		} else {
			for (ApplicationInfo applicationInfo : installedAppList) {
				if (pm.getLaunchIntentForPackage(applicationInfo.packageName) != null
						&& !ownPgk.equals(applicationInfo.packageName)) {
					appList.add(applicationInfo);
				}
			}
			return appList;
		}
	}

	public static String killRunningTasks(Context context) {
		PackageManager pm = context.getPackageManager();
		ActivityManager am = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);
		List<RunningTaskInfo> runningTaskInfos = am
				.getRunningTasks(Integer.MAX_VALUE);
		String result = "\nClosed/Restarted the following processes: \n";
		if ((runningTaskInfos == null) || (runningTaskInfos.size() == 0)) {
			return result;
		}

		for (RunningTaskInfo runningTaskInfo : runningTaskInfos) {
			String name = runningTaskInfo.topActivity.getClassName();
			Logging.log(name);
			String pck = runningTaskInfo.topActivity.getPackageName();
			if (!pck.equals(context.getPackageName())) {
				try {
					result += "\n"
							+ pm.getApplicationLabel(pm.getApplicationInfo(pck,
									0));
				} catch (Exception e) {
				}

				am.killBackgroundProcesses(pck);

			}

		}
		List<ActivityManager.RunningAppProcessInfo> procList = getRunningAppProcessesList(context);
		if ((procList == null) || (procList.size() == 0)) {
			return result;
		}
		// Retrieve running processes from ActivityManager
		for (ActivityManager.RunningAppProcessInfo appProcInfo : procList) {
			if (appProcInfo.uid != context.getApplicationInfo().uid) {
				try {
					result += "\n"
							+ pm.getApplicationLabel(pm.getApplicationInfo(
									appProcInfo.pkgList[0], 0));
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				Process.killProcess(appProcInfo.pid);
			}
		}
		Logging.log(result);
		return result;

	}

	public static List<ActivityManager.RunningAppProcessInfo> getRunningAppProcessesList(
			Context context) {
		ActivityManager am = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);
		return am.getRunningAppProcesses();
	}

	public static List<ActivityManager.RecentTaskInfo> getRecentgetRecentTasks(
			Context context) {
		ActivityManager am = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);
		return am.getRecentTasks(Integer.MAX_VALUE,
				ActivityManager.RECENT_WITH_EXCLUDED);
	}

	public static List<ActivityManager.RecentTaskInfo> getRecentAppList(
			Context context) {
		ActivityManager am = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);
		List<ActivityManager.RecentTaskInfo> taskInfos = am.getRecentTasks(
				Integer.MAX_VALUE, ActivityManager.RECENT_WITH_EXCLUDED);
		return taskInfos;
	}

	// ==========================================================================
	public static String getApplicationLabel(Context context, String pck) {
		PackageManager packageManager = context.getPackageManager();
		ApplicationInfo info;
		try {
			info = packageManager.getApplicationInfo(pck, 0);
			return info.loadLabel(packageManager).toString();
		} catch (NameNotFoundException e) {
			return "Un-known";
		}

	}

	public static String getApplicationLabel(Context context,
			ApplicationInfo info) {
		return info.loadLabel(context.getPackageManager()).toString();

	}

	// ==========================================================================
	public static Drawable getApplicationIcon(Context context,
			ApplicationInfo info) {
		return info.loadIcon(context.getPackageManager());

	}

	public static Drawable getApplicationIcon(Context context, String pck) {
		PackageManager packageManager = context.getPackageManager();
		try {
			ApplicationInfo info = packageManager.getApplicationInfo(pck, 0);
			return info.loadIcon(packageManager);
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;

	}

	public static long getApplicationSize(Context context, ApplicationInfo info) {
		return new File(info.sourceDir).length();

	}

	public static long getApplicationSize(Context context, String sourceDir) {
		return new File(sourceDir).length();

	}

	public static String convertSizeIntoString(long size) {
		if (size <= 0)
			return "0";
		final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" };
		int digitGroups = (int) (Math.log10(size) / Math.log10(1000));
		return new DecimalFormat("#,##0.#").format(size
				/ Math.pow(1000, digitGroups))
				+ " " + units[digitGroups];

	}

	// ==========================================================================

	public static void uninstallApp(Context context, String packageName) {
		// Create new intent to launch Uninstaller activity
		Uri packageURI = Uri.parse("package:" + packageName);
		Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
		uninstallIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		context.startActivity(uninstallIntent);
	}

	public static void uninstallAppWithResult(Activity context,
			String packageName, int requestCode) {
		// Create new intent to launch Uninstaller activity
		Uri packageURI = Uri.parse("package:" + packageName);
		Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
		context.startActivityForResult(uninstallIntent, requestCode);
	}

	public static ArrayList<String> getPermissions(Context context, String pck) {
		PackageManager pm = context.getPackageManager();
		try {
			PackageInfo packageInfo = pm.getPackageInfo(pck,
					PackageManager.GET_PERMISSIONS);
			return new ArrayList<String>(
					Arrays.asList(packageInfo.requestedPermissions));
		} catch (NameNotFoundException e) {
			return null;
		}

	}

	// ==========================================================================
	public static void launchHomeApp(Context context) {
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.addCategory(Intent.CATEGORY_HOME);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		context.startActivity(intent);
	}

	public static void launchSettingsApp(Context context) {
		Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		context.startActivity(intent);
	}

	public static void launchWirelessSettings(Context context) {
		Intent intent = new Intent(
				android.provider.Settings.ACTION_WIRELESS_SETTINGS);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		context.startActivity(intent);
	}

	public static void launchCameraApp(Context context) {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		context.startActivity(intent);
	}

	public static void launchRecentApps() {
		try {
			Class<?> serviceManagerClass = Class
					.forName("android.os.ServiceManager");
			Method getService = serviceManagerClass.getMethod("getService",
					String.class);
			IBinder retbinder = (IBinder) getService.invoke(
					serviceManagerClass, "statusbar");
			Class<?> statusBarClass = Class.forName(retbinder
					.getInterfaceDescriptor());
			Object statusBarObject = statusBarClass.getClasses()[0].getMethod(
					"asInterface", IBinder.class).invoke(null,
					new Object[] { retbinder });
			Method clearAll = statusBarClass.getMethod("toggleRecentApps");
			clearAll.setAccessible(true);
			clearAll.invoke(statusBarObject);
		} catch (Exception e) {
		}

	}

	public static void launchGPSSettings(Context context) {
		Intent intent = new Intent(
				android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		context.startActivity(intent);
	}

	public static void launchApp(Context context, String pck) {
		PackageManager packageManager = context.getPackageManager();
		Intent intent = packageManager.getLaunchIntentForPackage(pck);
		if (null == intent) {
			return;
		}
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		context.startActivity(intent);

	}

	public static void sendEmail(Activity context, String receiver,
			String subject, String body) {
		Intent intent = new Intent(Intent.ACTION_SEND);
		intent.setType("message/rfc822");
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
				| Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
		intent.putExtra(Intent.EXTRA_EMAIL, new String[] { receiver });
		intent.putExtra(Intent.EXTRA_SUBJECT, subject);
		try {
			context.startActivity(Intent.createChooser(intent, "Send mail..."));
			context.overridePendingTransition(R.anim.abc_fade_in,
					R.anim.abc_fade_out);
		} catch (android.content.ActivityNotFoundException ex) {
		}
	}

	public static void share(Context context, String path) {
		Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
				| Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
		intent.setType("file/*");
		intent.setData(Uri.fromFile(new File(path)));
		context.startActivity(Intent.createChooser(intent, ""));
	}

	// Start Activity
	// =======================================================================
	public static void launchActivity(Context context, Class<?> clazz) {
		Intent intent = new Intent(context, clazz);
		intent.setFlags(IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startActivity(intent);
	}

	public static void launchActivity(Activity context, Class<?> clazz,
			String action) {
		Intent intent = new Intent(context, clazz);
		intent.setFlags(IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
		intent.setAction(action);
		context.startActivity(intent);
		context.overridePendingTransition(R.anim.abc_fade_in,
				R.anim.abc_fade_out);
	}

	public static void launchActivity(Activity context, Class<?> clazz,
			boolean clearTask) {
		Intent intent = new Intent(context, clazz);
		if (clearTask) {
			intent.setFlags(IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		}
		context.startActivity(intent);
		context.overridePendingTransition(R.anim.abc_fade_in,
				R.anim.abc_fade_out);
	}

	public static void launchActivity(Activity context, Class<?> clazz,
			String action, Bundle bundle, boolean clearTask) {
		Intent intent = new Intent(context, clazz);
		if (clearTask) {
			intent.setFlags(IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		}
		intent.setAction(action);
		intent.putExtras(bundle);
		context.startActivity(intent);
		context.overridePendingTransition(R.anim.abc_fade_in,
				R.anim.abc_fade_out);
	}

	public static void launchActivity(Context context, Class<?> clazz,
			String action, Bundle bundle, boolean clearTask) {
		Intent intent = new Intent(context, clazz);
		if (clearTask) {
			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		}
		intent.setAction(action);
		intent.putExtras(bundle);
		context.startActivity(intent);
	}

	public static void showPackageDetail(Context activity, String pkg) {
		boolean launched = false;

		try {
			Intent intent = new Intent(
					"android.settings.APPLICATION_DETAILS_SETTINGS");
			Uri uri = Uri.parse("package:" + pkg);
			Logging.log(uri);
			intent.setData(uri);
			activity.startActivity(intent);
			launched = true;
		} catch (Throwable e) {
			launched = false;
			e.printStackTrace();
		}

		if (launched == false) {
			try {
				Intent intent = new Intent();
				intent.setClassName("com.android.settings",
						"com.android.settings.InstalledAppDetails");
				intent.putExtra("pkg", pkg);
				activity.startActivity(intent);
				launched = true;
			} catch (Throwable e) {
				launched = false;
				e.printStackTrace();
			}
		}
	}
}
